﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ComicIsland.Common.Entities.LocalDatabase;
using ComicIsland.Common.StorageHelper;

/**
 * 创建时间：2015/1/4 17:24:23
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 */
namespace ComicIsland.Common
{
    public class AsyncCacheImageTask
    {
        private const int BUFFER_SIZE = 2048;

        private WaitCallback callback;

        private HttpWebRequest request;

        private IAsyncResult iasyncresult;

        public IAsyncResult Iasyncresult { get; set; }

        public LDBComicChapterImage dbImage { get; set; }

        public AsyncCacheImageTask(LDBComicChapterImage dbImage)
        {
            this.dbImage = dbImage;
            this.callback = new WaitCallback(this.Load);
        }

        public void Dispose()
        {
            if (this.request == null)
            {
                return;
            }
            try
            {
                if (!this.iasyncresult.IsCompleted)
                {
                    this.request.EndGetResponse(this.iasyncresult);
                    this.request.Abort();
                }
            }
            catch
            {
            }
        }

        private void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            byte[] array = null;
            int statusCode = 0;
            try
            {
                HttpWebResponse httpWebResponse = (HttpWebResponse)((HttpWebRequest)asynchronousResult.AsyncState).EndGetResponse(asynchronousResult);
                statusCode = (int)httpWebResponse.StatusCode;
                if (statusCode == 200)
                {
                    using (Stream responseStream = httpWebResponse.GetResponseStream())
                    {
                        try
                        {
                            BinaryReader binaryReader = new BinaryReader(responseStream);
                            MemoryStream memoryStream = new MemoryStream();
                            byte[] numArray = new byte[2048];
                            long contentLength = httpWebResponse.ContentLength;
                            int num = 0;
                            long num1 = (long)0;
                            while (true)
                            {
                                int num2 = binaryReader.Read(numArray, 0, 2048);
                                num = num2;
                                if (num2 == 0)
                                {
                                    break;
                                }
                                memoryStream.Write(numArray, 0, num);
                                num1 = num1 + (long)num;
                                if (this.OnLoadProcessEvent != null && contentLength > (long)0)
                                {
                                    this.OnLoadProcessEvent(this, new CacheLoadProcessEventArgs(num1, contentLength));
                                }
                            }
                            memoryStream.Flush();
                            array = memoryStream.ToArray();
                            memoryStream.Close();
                            binaryReader.Close();
                            //
                            string filePath = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, dbImage.ComicId, "_", dbImage.PartId, "_", MD5.GetMd5String(dbImage.ImageUrl));
                            using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
                            using (var fileStream = isolatedStorageFile.OpenFile(filePath, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                responseStream.CopyTo(fileStream);
                                fileStream.Close();
                                fileStream.Dispose();
                            }
                            if (this.OnLoadCompleteEvent != null)
                            {
                                this.OnLoadCompleteEvent(this, new CacheLoadCompleteEventArgs(array, filePath));
                            }
                        }
                        catch (Exception err)
                        {
                            if (this.OnLoadErrorEvent != null)
                            {
                                this.OnLoadErrorEvent(this, new CacheLoadErrorEventArgs(statusCode, string.Concat("数据读写失败", err.Message)));
                            }
                        }
                    }
                }
                else if (this.OnLoadErrorEvent != null)
                {
                    this.OnLoadErrorEvent(this, new CacheLoadErrorEventArgs(statusCode, string.Concat("HTTP请求错误 ", statusCode)));
                }
                httpWebResponse.Dispose();
            }
            catch (Exception err)
            {
                if (this.OnLoadErrorEvent != null)
                {
                    this.OnLoadErrorEvent(this, new CacheLoadErrorEventArgs(statusCode, string.Concat("网络请求错误", err.Message)));
                }
            }
        }

        private void Load(object o)
        {
            try
            {
                string filePath = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, dbImage.ComicId, "_", dbImage.PartId, "_", MD5.GetMd5String(dbImage.ImageUrl));
                using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!IsolatedStorageHelper.Instance.FileExists(filePath))
                    {
                        this.LoadDataFromUrl(this.dbImage.ImageUrl);
                        return;
                    }
                    else
                    {
                        using (IsolatedStorageFileStream isoStream = store.OpenFile(filePath, FileMode.Open))
                        {
                            Stream stream = new MemoryStream();
                            isoStream.CopyTo(stream);
                            isoStream.Close();
                            isoStream.Dispose();
                            store.Dispose();

                            if (this.OnLoadCompleteEvent != null)
                            {
                                this.OnLoadCompleteEvent(this, new CacheLoadCompleteEventArgs(new Helper().StreamToBytes(stream), filePath));
                            }
                        }
                    }
                }
            }
            catch (Exception err)
            {

            }
        }

        private void LoadDataFromUrl(string url)
        {
            string str = url;
            try
            {
                this.request = WebRequest.CreateHttp(str);
                this.request.Headers["Accept-Language"] = "zh-cn,en-us;q=0.7,en;q=0.3";
                this.request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                //this.request.UserAgent = Constants.UserAgent;
                this.iasyncresult = this.request.BeginGetResponse(new AsyncCallback(this.GetResponseCallback), this.request);
            }
            catch (Exception exception1)
            {
                Exception exception = exception1;
                if (this.OnLoadErrorEvent != null)
                {
                    this.OnLoadErrorEvent(this, new CacheLoadErrorEventArgs(0, string.Concat("网络请求错误,", exception.Message)));
                }
            }
        }

        public void Start()
        {
            ThreadPool.QueueUserWorkItem(this.callback);
        }

        public event Action<AsyncCacheImageTask, CacheLoadCompleteEventArgs> OnLoadCompleteEvent;

        public event Action<AsyncCacheImageTask, CacheLoadErrorEventArgs> OnLoadErrorEvent;

        public event Action<AsyncCacheImageTask, CacheLoadProcessEventArgs> OnLoadProcessEvent;
    }

    public class CacheLoadCompleteEventArgs : EventArgs
    {
        public object Data { get; set; }
        public string FilePath { get; set; }

        public CacheLoadCompleteEventArgs(object data, string filePath)
        {
            this.Data = data;
            this.FilePath = filePath;
        }
    }

    public class CacheLoadErrorEventArgs : EventArgs
    {
        public string ErrorMessage { get; set; }
        public int ResponseCode { get; set; }

        public CacheLoadErrorEventArgs(int responseCode, string errorMessage)
        {
            this.ResponseCode = responseCode;
            this.ErrorMessage = errorMessage;
        }
    }

    public class CacheLoadProcessEventArgs : EventArgs
    {
        public long CurByteNum { get; set; }

        public long TotalByteNum { get; set; }

        public CacheLoadProcessEventArgs(long curByteNum, long totalByteNum)
        {
            this.CurByteNum = curByteNum;
            this.TotalByteNum = totalByteNum;
        }
    }
}
